﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.ComponentModel;
using System.Collections.Generic;
using System.Windows.Data;
using System.IO;
using System.Linq;

using Cinch;
using MEFedMVVM.ViewModelLocator;
using MEFedMVVM.Services.Contracts;
using MEFedMVVM.Common;
using System.Windows.Threading;
using System.Threading;
using System.Configuration;


namespace Anata.Client
{
    /// <summary>
    /// This is a workspace type ViewModel, which is created by some code in the <c>MainWindowViewModel</c>
    /// and the DataTemplate in the <c>MainWindow.xaml</c>
    /// 
    /// This is the main ViewModel of the demo app, and this ViewModel makes use
    /// of pretty much all the Cinch services available.
    /// 
    /// This ViewModel is also able to operate in design mode by using the
    /// <c>IImageProvider</c> data service, which can either be a runtime service or a design time service
    /// 
    /// This ViewModel is also expecting some contextual data from the <c>IViewAwareStatus</c> service
    /// (as we are using a View 1st type of development in CinchV2). This contextual data is the
    /// image path that the <c>IImageProvider</c> data service uses to fetch images.
    /// 
    /// As such this ViewModel expects the <c>IViewAwareStatus</c> service which allows the ViewModel
    /// to examine this contextual view data
    /// 
    /// Anyway in this ViewModel you will find a demo of most of the services Cinch has to offer
    /// </summary>
    [ExportViewModel("CabangListViewModel")]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class CabangListViewModel : ViewModelBase
    {
        #region Data
        //private ViewMode currentViewMode = ViewMode.AddMode;

        #region Data.Primitives
        private String filterKeyword = "";

        private bool isAllLoaded = false;
        private int pageLoaded = 0;
        private DispatcherTimer filterTimer;
        #endregion

        //private IEnumerable<DataWrapperBase> cachedListOfDataWrappers;
        
        #region Data.Rules
        #endregion
        
        #region Data.VMs
        private DispatcherNotifiedObservableCollection<CabangThumbnailViewModel> cabangs;
        private ICollectionView cabangsCV;
        #endregion

        #region Data.Services
        private IViewAwareStatus viewAwareStatusService;
        private IMessageBoxService messageBoxService;
        private IUIVisualizerService uiVisualizerService;
        private ICabangProvider cabangProvider;
        private IReferenceProvider referenceProvider;
        #endregion

        #endregion

        #region Constructor
        [ImportingConstructor]
        public CabangListViewModel(
            IMessageBoxService messageBoxService,
            IUIVisualizerService uiVisualizerService,
            IViewAwareStatus viewAwareStatusService,
            ICabangProvider cabangProvider,
            IReferenceProvider referenceProvider)
        {
            #region Constructor.SetupServices
            this.messageBoxService = messageBoxService;
            this.uiVisualizerService = uiVisualizerService;
            this.viewAwareStatusService = viewAwareStatusService;
            this.viewAwareStatusService.ViewLoaded += ViewAwareStatusService_ViewLoaded;
            this.cabangProvider = cabangProvider;
            this.referenceProvider = referenceProvider;
            #endregion

            #region Constructor.SetupCommands
            CabangNewCommand = new SimpleCommand<Object, Object>(CanExecuteCabangNewCommand, ExecuteCabangNewCommand);
            CabangRefreshCommand = new SimpleCommand<Object, Object>(CanExecuteCabangRefreshCommand, ExecuteCabangRefreshCommand);
            CabangSelectCommand = new SimpleCommand<Object, Object>(CanExecuteCabangSelectCommand, ExecuteCabangSelectCommand);
            CabangFilterKeyUpCommand = new SimpleCommand<Object, Object>(CanExecuteCabangFilterKeyUpCommand, ExecuteCabangFilterKeyUpCommand);
            #endregion

            #region Constructor.SetupDataWrappers
            #endregion

            #region Constructor.SetupValidationRules
            #endregion

            #region Constructor.SetupVMs
            Cabangs = new DispatcherNotifiedObservableCollection<CabangThumbnailViewModel>();
            CabangsCV = CollectionViewSource.GetDefaultView(cabangs);
            //CabangsCV.SortDescriptions.Add(new SortDescription("Nama", ListSortDirection.Ascending));
            #endregion

            Mediator.Instance.Register(this);

            #region Constructor.Filter
            filterTimer = new DispatcherTimer();
            filterTimer.Interval = TimeSpan.FromMilliseconds(
                Int32.Parse(ConfigurationManager.AppSettings["FilterResponsiveness"].ToString()));
            filterTimer.Tick += new EventHandler(LazyFilterCallback);
            #endregion
        }
        #endregion

        #region Public Properties

        #region Public.Commands
        public SimpleCommand<Object, Object> CabangNewCommand { get; private set; }
        public SimpleCommand<Object, Object> CabangRefreshCommand { get; private set; }
        public SimpleCommand<Object, Object> CabangFilterKeyUpCommand { get; private set; }
        public SimpleCommand<Object, Object> CabangSelectCommand { get; private set; }
        #endregion

        #region Public.ViewMode
        #endregion

        #region Public.Data
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs cabangsChangeArgs =
            ObservableHelper.CreateArgs<CabangListViewModel>(x => x.Cabangs);
        public DispatcherNotifiedObservableCollection<CabangThumbnailViewModel> Cabangs
        {
            get { return cabangs; }
            set
            {
                cabangs = value;
                NotifyPropertyChanged(cabangsChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs cabangsCVChangeArgs =
            ObservableHelper.CreateArgs<CabangListViewModel>(x => x.CabangsCV);
        public ICollectionView CabangsCV
        {
            get { return cabangsCV; }
            set
            {
                cabangsCV = value;
                NotifyPropertyChanged(cabangsCVChangeArgs);
            }
        }



        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs filterKeywordChangeArgs =
            ObservableHelper.CreateArgs<CabangListViewModel>(x => x.FilterKeyword);
        public String FilterKeyword
        {
            get { return filterKeyword; }
            set
            {
                filterKeyword = value;
                NotifyPropertyChanged(filterKeywordChangeArgs);
                LazyFilter();
            }
        }
        #endregion

        #region Public.CachedCollection
        #endregion

        #endregion

        #region Command Handlers
        /// <summary>
        /// </summary>
        private bool CanExecuteCabangNewCommand(Object args)
        {
            return true;
        }
        /// <summary>
        /// </summary>
        private void ExecuteCabangNewCommand(Object args)
        {
            CabangThumbnailViewModel ctvm = new CabangThumbnailViewModel();
            cabangs.Add(ctvm);
            Mediator.Instance.NotifyColleagues<CabangThumbnailViewModel>(
                "TryActivateCabangDetail", ctvm);
        }

        /// <summary>
        /// </summary>
        private bool CanExecuteCabangRefreshCommand(Object args)
        {
            return true;
        }
        /// <summary>
        /// </summary>
        private void ExecuteCabangRefreshCommand(Object args)
        {
            pageLoaded = 0;
            isAllLoaded = false;
            cabangs.Clear();
            cabangProvider.LazyFetchCabangs(pageLoaded, PostLoadCabangs);
        }

        /// <summary>
        /// </summary>
        private bool CanExecuteCabangFilterKeyUpCommand(Object args)
        {
            return true;
        }
        /// <summary>
        /// </summary>
        private void ExecuteCabangFilterKeyUpCommand(Object args)
        {
            LazyFilter();
        }
        
        /// <summary>
        /// </summary>
        private bool CanExecuteCabangSelectCommand(Object args)
        {
            return true;
        }
        /// <summary>
        /// </summary>
        private void ExecuteCabangSelectCommand(Object args)
        {
            CabangThumbnailViewModel ctvm = (CabangThumbnailViewModel)CabangsCV.CurrentItem;
            if (ctvm != null)
            {
                Mediator.Instance.NotifyColleagues<CabangThumbnailViewModel>(
                    "TryActivateCabangDetail", ctvm);
            }
        }

        #endregion

        #region Mediator Message Sinks
        [MediatorMessageSink("RemoveCabangThumbnail")]
        private void RemoveCabangThumbnail(CabangThumbnailViewModel ctvm)
        {
            if (this.cabangs.Contains(ctvm))
            {
                this.cabangs.Remove(ctvm);
            }
        }

        [MediatorMessageSink("TryHighlightCabangThumbnail")]
        private void TryHighlightCabangThumbnail(CabangThumbnailViewModel ctvm)
        {
            if (this.cabangsCV.Contains(ctvm) && !ctvm.Equals(this.cabangsCV.CurrentItem))
            {
                this.cabangsCV.MoveCurrentTo(ctvm);
                Console.WriteLine("posisi #" + CabangsCV.CurrentPosition + ": " + CabangsCV.CurrentItem);
            }
        }

        [MediatorMessageSink("TryRemoveCabangThumbnail")]
        private void TryRemoveCabangThumbnail(CabangThumbnailViewModel ctvm)
        {
            if (this.CabangsCV.Contains(ctvm))
            {
                if (ctvm.IdCabang != 0)
                {
                    CustomDialogResults result = messageBoxService.ShowYesNo("Yakin Hapus?", CustomDialogIcons.Question);
                    if (result == CustomDialogResults.Yes)
                    {
                        cabangs.Remove(ctvm);
                    }
                }
                else
                {
                    cabangs.Remove(ctvm);
                }
            }
        }

        #endregion

        #region PrivateMethods
        #region PrivateMethods.ViewLoaded
        private void ViewAwareStatusService_ViewLoaded()
        {
            cabangProvider.LazyFetchCabangs(pageLoaded, PostLoadCabangs);
        }
        #endregion

        #region PrivateMethods.Filter
        private void LazyFilter()
        {
            filterTimer.Stop();
            filterTimer.Start();
        }
        private void LazyFilterCallback(object sender, EventArgs e)
        {
            Console.WriteLine("stopped typing, filtering with keyword: " + filterKeyword);
            filterTimer.Stop();
            if (filterKeyword != "")
            {
                cabangsCV.Filter = new Predicate<object>(LazyFilterPredicate);
            }
            else
            {
                cabangsCV.Filter = null;
            }
        }
        private bool LazyFilterPredicate(object row)
        {
            CabangThumbnailViewModel ctvm = row as CabangThumbnailViewModel;
            return (ctvm.Nama.ToLower().Contains(filterKeyword.ToLower()));
        }
        #endregion

        #region PrivateMethods.PostLoader
        private void PostLoadCabangs(List<CabangThumbnailViewModel> ctvms)
        {
            //rekursif sampai semua diload
            int pageSize = Int32.Parse(ConfigurationManager.AppSettings["LazyLoadPageSize"].ToString());
            foreach (CabangThumbnailViewModel ctvm in ctvms)
            {
                cabangs.Add(ctvm);
            }

            if (ctvms.Count != pageSize)
            {
                //basis
                //sudah habis, done loading
                isAllLoaded = true;
                CabangsCV.Refresh();
            }
            else
            {
                //rekurens
                ++pageLoaded;
                cabangProvider.LazyFetchCabangs(pageLoaded, PostLoadCabangs);
            }
        }
        #endregion

        #region PrivateMethods.Saver
        /// <summary>
        /// </summary>
        private void PostRemoveCabang(CabangThumbnailViewModel ctvm)
        {
            if (ctvm != null)
            {
                if (this.CabangsCV.Contains(ctvm))
                {
                    cabangs.Remove(ctvm);
                }
            }
            else
            {
                messageBoxService.ShowError("gagal remove, coba lagi");
            }
        }
        #endregion
        #endregion
    }

}
